#ifndef _PCAM_DFU_H
#define _PCAM_DFU_H

#include "mmpf_typedef.h"

#define	SFLASH_WIP	0x01
#define	SFLASH_WEL	0x02
#define	SFLASH_SECTOR_SIZE	0x1000
#define	SFLASH_PAGE_SIZE	0x100


typedef struct
{
	MMP_BOOL bDefault;//:1,// = 1
	MMP_BOOL bRemoveHeader;// = 1
	MMP_BOOL bKeyRom;// = 1
	MMP_BOOL bPassword;// = 1
	MMP_BOOL bPartialUpdate;// = 1
	MMP_BOOL bHidden;// = 1
	MMP_BOOL bUpdateSize;// = 1
	MMP_BOOL bExtendedData;// = 1
	MMP_BOOL bEncryption;// = 1
	MMP_BOOL bChecksum;// = 1
	MMP_BOOL bBinaryComparasion;// = 1
} ROM_FILE_DESC_FLAG;

typedef struct
{
	MMP_ULONG dwNextROMOffset;	// 	;4
	MMP_ULONG dwROMAddr;			//	;4
	ROM_FILE_DESC_FLAG *dwFlags;			//	;4
	MMP_ULONG dwROMDataSize;
	MMP_UBYTE bROMNameSize;		//	;1
	MMP_UBYTE *strROMName;
	MMP_ULONG dwExtSize;
	MMP_UBYTE *bExtData;
	MMP_ULONG dwBinaryUpdateSize;
	MMP_UBYTE bPasswordSize;		//	; 4
	MMP_UBYTE *strPassword;		// = "1234"
	MMP_UBYTE *bDataPtr;
} ROM_FILE_DESC;

#if (SUPPORT_ISP_ENGINEERING_MODE_FUNCTION==1)||(SUPPORT_ISP_CALIBRATION_FUNCTION==1)
//These are for 8433 reduced sizes.
#define ISP_LS_TBL_R_NUM    (128) //16*8
#define ISP_LS_TBL_G_NUM    (128) //16*8
#define ISP_LS_TBL_B_NUM    (128) //16*8

#define ISP_CS_POS_X_NUM    (13)
#define ISP_CS_POS_Y_NUM    (10)
#define ISP_CS_TBL_R_NUM    (154) //14*11
#define ISP_CS_TBL_G_NUM    (154) //14*11
#define ISP_CS_TBL_B_NUM    (154) //14*11

#define ISP_GAMMA_TBL_R_NUM (33) //
#define ISP_GAMMA_TBL_G_NUM (33) //
#define ISP_GAMMA_TBL_B_NUM (33) //
#if (CHIP==VSN_V2)
#define ISP_GAMMA_TBL_R_OPR_BASE    (0x7280)    //(0x8007280)
#define ISP_GAMMA_TBL_G_OPR_BASE    (0x72A0)    //(0x80072A0)
#define ISP_GAMMA_TBL_B_OPR_BASE    (0x72C0)    //(0x80072C0)
#define ISP_GAMMA_TBL_R_LAST_ADDR   (0x72E0)    //(0x80072E0)
#define ISP_GAMMA_TBL_G_LAST_ADDR   (0x72E1)    //(0x80072E1)
#define ISP_GAMMA_TBL_B_LAST_ADDR   (0x72E2)    //(0x80072E2)
#endif

#define XU_CMD_HEADER_TAG_CHECK_SIZE (8) //"ISP_CALI", "ISP_IQTB", "ISP_GAMA"

typedef struct _ISP_AWB_TABLE
{
    MMP_USHORT gainr; // AWB gain R
    MMP_USHORT gaingr;// AWB gain GR
    MMP_USHORT gaingb;// AWB gain GB
    MMP_USHORT gainb;// AWB gain B
}ISP_AWB_TABLE;

typedef struct _ISP_LS_TABLE
{
    MMP_USHORT basex; // LS base x
    MMP_USHORT basey;// LS base y
    MMP_USHORT offsetx;// LS offset x
    MMP_USHORT offsety;// LS offset y
    MMP_USHORT centerx;// LS center x
    MMP_USHORT centery;// LS center y
    MMP_USHORT ratex;// LS rate x
    MMP_USHORT ratey;// LS rate y
    MMP_USHORT tblr[ISP_LS_TBL_R_NUM];// LS table r
    MMP_USHORT tblg[ISP_LS_TBL_G_NUM];// LS table g
    MMP_USHORT tblb[ISP_LS_TBL_B_NUM];// LS table b
}ISP_LS_TABLE;

typedef struct _ISP_CS_TABLE
{
    MMP_USHORT basex; // CS base x
    MMP_USHORT basey;// CS base y
    MMP_USHORT offsetx;// CS offset x
    MMP_USHORT offsety;// CS offset y
    MMP_USHORT centerx;// CS center x
    MMP_USHORT centery;// CS center y
    MMP_USHORT scale;// CS rate x
    MMP_USHORT posx[ISP_CS_POS_X_NUM];// CS rate y
    MMP_USHORT posy[ISP_CS_POS_Y_NUM];// CS rate y
    MMP_USHORT tblr[ISP_CS_TBL_R_NUM];// CS table r
    MMP_USHORT tblg[ISP_CS_TBL_G_NUM];// CS table g
    MMP_USHORT tblb[ISP_CS_TBL_B_NUM];// CS table b
}ISP_CS_TABLE;

typedef struct _ISP_GAMMA_TABLE
{
    MMP_USHORT tblr[ISP_GAMMA_TBL_R_NUM]; // GAMMA table r
    MMP_USHORT tblg[ISP_GAMMA_TBL_G_NUM];// GAMMA table g
    MMP_USHORT tblb[ISP_GAMMA_TBL_B_NUM];// GAMMA table b
}ISP_GAMMA_TABLE;

#define SENSOR_ID_IN_XU_CALI_TABLE 1 //Set 0 to make sensor ID in XU command. Set 1 to make sensor ID in Ap2Fw IQ table header.
typedef struct _XU_CALI_TABLE_HEADER
{
    MMP_UBYTE tag[XU_CMD_HEADER_TAG_CHECK_SIZE]; // 'ISP_CALI'
    MMP_ULONG header_size;// header size in byte , exclude 8 bytes tag
    MMP_ULONG data_size;// calibration data size
    MMP_ULONG color_temp;// color temperature of this shading table
    MMP_ULONG lux;// LUX
#if SENSOR_ID_IN_XU_CALI_TABLE
    MMP_ULONG sensor_id;// 0 base, sensor ID
#endif
}XU_CALI_TABLE_HEADER;

#if 0
typedef struct _XU_IQ_TABLE_HEADER
{
    MMP_UBYTE tag[XU_CMD_HEADER_TAG_CHECK_SIZE]; // 'ISP_IQTB'
    MMP_ULONG header_size;// header size in byte, (offset from DWORD header_size to data beginning )
    MMP_ULONG data_size;// calibration data size
    MMP_ULONG sensor_id;// 0 base, sensor ID
    MMP_ULONG reserved;//
}XU_IQ_TABLE_HEADER;
#endif
//The data table from XU command
typedef struct _XU_CALI_TABLE
{
    XU_CALI_TABLE_HEADER pHeader; // XU CMD CALI table header
    ISP_AWB_TABLE pAWBTbl;// AWB table
    ISP_LS_TABLE pLSTbl;// LS table
    ISP_CS_TABLE pCSTbl;// CS table
}XU_CALI_TABLE;

//the header of the table stored in flash.
//Note that it is similar with XU_CALI_TABLE_HEADER but
// 1. without sensor ID.
// 2. flash_addr instead of header_size
typedef struct _FLASH_CALI_TABLE_HEADER
{
    MMP_ULONG flash_addr;// address in the flash in bytes.
    MMP_ULONG data_size;// calibration data size. The header size is excluded.
    MMP_ULONG color_temp;// color temperature of this shading table
    MMP_ULONG lux;// LUX
}FLASH_CALI_TABLE_HEADER;

typedef struct _ISP_CALI_DATA {
    ISP_AWB_TABLE pAWBTbl;// AWB table
    ISP_LS_TABLE pLSTbl;// LS table
    ISP_CS_TABLE pCSTbl;// CS table
} ISP_CALI_DATA;


#define UNDEFINED_FLASH_DATA 0xFFFFFFFF
#define NUM_CALI_FLASH_HEADER 3 //required number of calibration tables for each sensor in flash.
#define MAX_CALI_FLASH_HEADER 4 //max number of calibration tables for each sensor in flash.
#if NUM_CALI_FLASH_HEADER >= MAX_CALI_FLASH_HEADER
    #error MAX_CALI_FLASH_HEADER must > NUM_CALI_FLASH_HEADER to hold end address
#endif
/* The table stored in the flash
 * CALI burning flow:
 * 1. check if the address in m_caliFlashTable is there, then check if tag "ISP_CALI" is there
 * 2. If 1 is false, fill tag "ISP_CALI" and addr1, then fill the rest addresses as 0xFFFFFFFF.
 * 3. If 1 is true, is addr1 a valid address?
 * 4. if 3 is true, check the next address until it is false.
 *    attachment the data and write it back to flash.
 *
 * CALI clearing flow:
 * 1. check if the address in m_caliFlashTable is there. If it's true, clear tag to 0xFFFFFFFF.
 */
typedef struct _CALI_FLASH_TABLE
{
    MMP_UBYTE tag[XU_CMD_HEADER_TAG_CHECK_SIZE]; // 'ISP_CALI'
    FLASH_CALI_TABLE_HEADER header[MAX_CALI_FLASH_HEADER]; //multiple number of headers. The max is 8 for now.
    ISP_CALI_DATA * data;
}CALI_FLASH_TABLE;


typedef struct _XU_IQ_GAMMA_TABLE_HEADER
{
    MMP_UBYTE tag[XU_CMD_HEADER_TAG_CHECK_SIZE]; // 'ISP_GAMA'
    MMP_ULONG header_size;// header size in byte, (offset from DWORD header_size to data beginning )
    MMP_ULONG data_size;// gamma table size
    MMP_ULONG sensor_id;// 0 base, sensor ID
    MMP_ULONG reserved;//
}XU_IQ_GAMMA_TABLE_HEADER;

typedef struct _XU_IQ_GAMMA_TABLE
{
    XU_IQ_GAMMA_TABLE_HEADER pHeader; // xu cmd gamma table header
    ISP_GAMMA_TABLE pGAMMATbl;// gamma table
}XU_IQ_GAMMA_TABLE;

void USB_EraseCaliHeader(void);
MMP_USHORT USB_AppendCaliData(XU_CALI_TABLE *xu_cali_data, MMP_UBYTE sensor_id);
MMP_USHORT USB_ReadCaliData(MMP_ULONG* cali_flash_addr, MMP_UBYTE sensor_id);
MMP_USHORT USB_ApplyCaliData(MMP_USHORT sensor_id);
#else
#define USB_ApplyCaliData(sensor_id) 0
#endif
MMP_USHORT USB_ResetFlash(void);

MMP_ERR USB_Read840BootFirmware(MMP_UBYTE *FWImagePtr, MMP_ULONG FWImageSize);
#if (CHIP_VER == VER_A)  // without ROM boot
MMP_ERR USB_Read840PCCAMFirmware(MMP_UBYTE *FWImagePtr, MMP_ULONG FWImageSize);
#endif
MMP_ERR USB_DownloadFWInitialize(void);
MMP_ERR USB_DownloadFWData(MMP_UBYTE *data, MMP_USHORT len);
MMP_ERR USB_Burning840FW2SFlash(void);
#if (CHIP_VER == VER_A)  // without ROM boot
MMP_ERR	Burning840PCCAMFirmwareImage(MMP_ULONG FlashAddr);
MMP_ERR BurningBootCode(void);
#endif
#if (CHIP_VER == VER_B)  // with ROM boot
MMP_ERR Burning845xFWImage(void);
#endif

#if SUPPORT_ISP_CALIBRATION_FUNCTION
MMP_USHORT USB_TestCurCaliData(void);
#else
#define USB_TestCurCaliData()
#endif

#endif
